import React, { Component } from "react";
import { connect } from "react-redux";
import { testSync, fun } from "@/reducer/reduxExercise";
import { post } from "@/Utils/http";

class ReduxPromise extends Component {
  state = {
    status: false,
  };

  abc = () => {
    this.props.fun("aaaa");
  };

  /**
   * 使用redux来处理异步
   */
  promiseHandler = () => {
    // 请求发起前，修改状态
    this.setState({ status: "loading" });
    // 使用redux调用异步请求
    this.props
      .testSync({ username: "superAdmin", password: "1Qa2Ws3Ed" })
      .then((res) => {
        // 请求完成后，修改状态
        this.setState({ status: true });
      });
  };

  /**
   * 渲染菜单内容
   */
  renderMenus(menus) {
    return menus.map((item) => (
      <div key={item.id}>
        <span className="key">{item.id}:</span>路径：{item.path}，模块名：
        {item.name}
      </div>
    ));
  }
  render() {
    console.log(this.props);
    return (
      <div className="redux-main">
        <button onClick={this.abc}>{this.props.reduxExercise.abc}123456</button>
        <h4 className="title">reduxPromise</h4>
        <div className="desc">promise相对来说比较简单：</div>
        <button onClick={this.promiseHandler}>点击发起异步请求</button>
        <br />
        <h5>
          {!this.state.status
            ? "请求发生前状态"
            : this.state.status === "loading"
            ? "请求中..."
            : "请求发生后状态"}
        </h5>
        <hr />
        <div className="status-list">
          {this.props.reduxExercise &&
            Object.entries(this.props.reduxExercise).map(([key, value]) => (
              <div key={key} className="single">
                <span className="key">{key}:</span>
                {typeof value === "object"
                  ? this.renderMenus(value)
                  : value || "没有值"}
              </div>
            ))}
        </div>
        <hr />
      </div>
    );
  }
}

// react-redux的用法
/**
 * 参数一 mapStateToProps 可选 我们需要react-redux将哪些状态映射（注入）到我们的组件里去？
 * @param {*} state store状态树
 * @param {*} ownProps 当前组件的props
 * @returns 需要映射到组件中去的状态
 *
 * mapStateToProps执行后应该返回一个对象，对象里的键值对都会被映射到我们的props中去
 * mapStateToProps会订阅 Store，每当state更新的时候，就会自动执行，计算并修改注入的内容，从而触发我们组件的props变化，进而重新渲染整个组件
 * 需要注意的是，这个参数是可选的，如果我们不传入这个参数，表示我们当前组件并不需要依赖store中的状态来渲染
 */
function mapStateToProps(state, ownProps) {
  return {
    reduxExercise: state.reduxExercise,
  };
}

/**
 * 参数二 mapDispatchToProps 可选 我们需要将哪些action方法映射（注入）到我们的组件里去？
 * @param {*} dispatch store.dispatch方法，用于将指定的action对象派发到store中去
 * @param {*} ownProps 当前组件的props
 * @returns 映射到props中去的action方法
 */
function mapDispatchToProps(dispatch, ownProps) {
  return {
    testSync(params) {
      // 这里的return是为了让我们的调用位置可以继续接收promise返回的信息
      return dispatch({
        type: "promise",
        payload: post("/api/mockv1/login", { ...params }).then((res) => {
          console.log(res);
          return res;
        }),
      });
    },
  };
}

/**
 * mapDispatchToProps 也可以是一个对象，这个对象中属性的值必须是一个能返回action的函数，
 * reactRedux会将这个函数当成是一个action生成器，函数中返回的action将会被reactRedux自动派发到store中去
 * 比如下面这个objectMapDispatchToProps，它与上面的mapDispatchToProps作用是一致的
 */
const objectMapDispatchToProps = {
  testSync(params) {
    return {
      type: "promise",
      payload: post("/api/mockv1/login", params),
    };
  },
};

function createAction(res) {
  return { type: "promise", payload: res };
}
// // 完成所有的计算
const ReduxComponent = connect(mapStateToProps, {
  testSync: testSync,
  fun: fun,
});
// // 抛出
export default ReduxComponent(ReduxPromise);

// 抛出  老杨的方法
// export default connect(mapStateToProps, {
//   testSync(payload) {
//     return (dispatch, _, { post }) => {
//       dispatch({ type: "promise", payload: { status: "loading" } });
//       return new Promise((reslove, reject) => {
//         post("/app/mockv1/login", payload)
//           .then((res) => {
//             reslove(res);
//             dispatch({
//               type: "promise",
//               payload: { ...res, status: "success" },
//             });
//           })
//           .catch((err) => {
//             reject(err);
//             dispatch({ type: "promise", payload: { status: "fail" } });
//           });
//       });
//     };
//   },
//   fun: function (params) {
//     return (dispatch, _, { post }) => {
//       new Promise((reslove, reject) => {
//         setTimeout(() => {
//           reslove({ aaa: "aaaaa" + params });
//         }, 3000);
//       }).then((res) => {
//         console.log(res);
//         dispatch({ type: "thunk", payload: res });
//       });
//     };
//   },
// })(ReduxPromise);
